package utils

import "fmt"

// A.B.C.D/M
// A : 10-222
// B : 2-254
// C : 2-254
// D : 1-254
// M : 24

type CidrMask24 struct {
	A     int
	B     int
	C     int
	diter int
}

func NewCidrMask24FromCidrMask(cm *CidrMask) *CidrMask24 {
	return &CidrMask24{
		A: cm.A,
		B: cm.B,
		C: cm.C,
	}
}

func (cm *CidrMask24) String() string {
	return fmt.Sprintf("%d.%d.%d.0/24", cm.A, cm.B, cm.C)
}

func (cm *CidrMask24) ReSetIp() {
	cm.diter = 1
}

func (cm *CidrMask24) NextIp() string {
	if cm.diter > 254 {
		return ""
	}
	ip := fmt.Sprintf("%d.%d.%d.%d/24", cm.A, cm.B, cm.C, cm.diter)
	cm.diter++
	return ip
}

type CidrPoolMask24 struct {
	cidrVis map[string]bool
	curA    int
	curB    int
	curC    int
	mask    int
}

func NewCidrPoolMask24() *CidrPoolMask24 {
	return &CidrPoolMask24{
		cidrVis: make(map[string]bool),
		curA:    10,
		curB:    2,
		curC:    2,
		mask:    24,
	}
}

func (cpm *CidrPoolMask24) AddOneCidrMask(cidr interface{}) bool {
	var c24 *CidrMask24 = nil
	// 类型转换
	if cidrStr, ok := cidr.(string); ok {
		c, err := ParseCidrMask(cidrStr)
		if err != nil {
			return false
		}
		if c.Mask != 24 {
			return false
		}
		c24 = NewCidrMask24FromCidrMask(c)
	} else if cidrCm, ok := cidr.(*CidrMask); ok {
		c24 = NewCidrMask24FromCidrMask(cidrCm)
	} else if cidrCm, ok := cidr.(CidrMask); ok {
		c24 = NewCidrMask24FromCidrMask(&cidrCm)
	} else {
		return false
	}
	if c24 == nil {
		return false
	}
	// 记录
	if cpm.cidrVis[c24.String()] {
		return false
	} else {
		cpm.cidrVis[c24.String()] = true
		return true
	}
}

func (cpm *CidrPoolMask24) IsCidrInPool(cm *CidrMask24) bool {
	cidrStr := cm.String()
	if cpm.cidrVis[cidrStr] {
		return true
	} else {
		return false
	}
}

func (cpm *CidrPoolMask24) GetCidr() *CidrMask24 {
	var cidr CidrMask24
	for {
		cidr.A = cpm.curA
		cidr.B = cpm.curB
		cidr.C = cpm.curC
		cpm.curC++
		if cpm.curC > 254 {
			cpm.curC = 2
			cpm.curB++
			if cpm.curB > 254 {
				cpm.curB = 2
				cpm.curA++
				if cpm.curA > 222 {
					break
				}
			}
		}
		// 检查cidr是否已经分配过
		cidrStr := cidr.String()
		if cpm.cidrVis[cidrStr] {
			continue
		} else {
			cpm.cidrVis[cidr.String()] = true
			return &cidr
		}
	}
	return nil
}
